const dayjs = require('dayjs');
/**
 * 统一错误处理模块
 * 处理应用中的各类错误，提供一致的错误处理体验
 */

import { observable, action } from 'mobx-miniprogram';
import { uiStore } from './ui.js';
import { userStore } from './user.js';
import { standardizeGlobalStore } from '../helpers/store_standardizer.js';

// 错误类型
export const ERROR_TYPES = {
  NETWORK: 'network',     // 网络错误
  AUTH: 'auth',           // 认证错误
  PERMISSION: 'permission', // 权限错误
  VALIDATION: 'validation', // 数据验证错误
  BUSINESS: 'business',   // 业务逻辑错误
  SYSTEM: 'system',       // 系统错误
  UNKNOWN: 'unknown',     // 未知错误
  API: 'api_error',        // API调用错误
  VALIDATION: 'validation_error', // 表单验证错误
  PERMISSION: 'permission_error', // 权限错误
  AUTH: 'auth_error',       // 认证错误
  SYSTEM: 'system_error',    // 系统错误
  UNKNOWN: 'unknown_error'   // 未知错误
};

// 错误处理器
export const errorHandler = {
  // 错误计数和限制
  _errorCounter: {
    count: 0,
    lastResetTime: dayjs().valueOf(),
    maxErrorsPerMinute: 5
  },
  
  /**
   * 处理页面错误
   * @param {Error|Object} error 错误对象
   * @param {String} moduleName 模块名称
   * @param {Object} options 附加选项
   * @returns {Boolean} 是否已处理
   */
  handlePageError: function(error, moduleName = null, options = {}) {
    console.error(`[${moduleName || 'App'}]`, error);
    
    // 错误频率限制
    if (!this._checkErrorLimit()) {
      console.warn('错误频率过高，部分错误被抑制');
      return false;
    }
    
    // 默认选项
    const defaultOptions = {
      showToast: true,    // 是否显示Toast
      showModal: false,   // 是否显示Modal
      updateUI: true,     // 是否更新全局UI状态
      toastDuration: 2000, // Toast持续时间
      logToServer: true   // 是否记录到服务器
    };
    
    const mergedOptions = { ...defaultOptions, ...options };
    const errorMessage = this._getErrorMessage(error);
    const errorType = this._getErrorType(error);
    
    // 创建标准错误对象
    const standardError = this._createStandardError(error, errorMessage, errorType);
    
    // 更新全局错误状态
    if (mergedOptions.updateUI) {
      uiStore.setError(moduleName, standardError);
    }
    
    // 显示错误提示
    if (mergedOptions.showToast) {
      this._showErrorToast(errorMessage, mergedOptions.toastDuration);
    }
    
    // 显示错误对话框
    if (mergedOptions.showModal) {
      this._showErrorModal(errorMessage, error);
    }
    
    // 记录到服务器
    if (mergedOptions.logToServer) {
      this._logErrorToServer(standardError, moduleName);
    }
    
    // 特殊错误处理
    this._handleSpecialErrors(error, errorType);
    
    return true;
  },
  
  /**
   * 处理API调用错误
   * @param {Error|Object} error 错误对象
   * @param {Boolean} silent 是否静默处理
   * @returns {Boolean} 是否已处理
   */
  handleApiError: function(error, silent = false) {
    console.error('[API Error]', error);
    
    // 错误频率限制
    if (!this._checkErrorLimit()) {
      console.warn('API错误频率过高，部分错误被抑制');
      return false;
    }
    
    if (silent) return true;
    
    const errorMessage = this._getErrorMessage(error);
    const errorType = this._getErrorType(error);
    
    // 创建标准错误对象
    const standardError = this._createStandardError(error, errorMessage, errorType);
    
    // 更新全局错误状态 - API错误通常用全局
    uiStore.setError(null, standardError);
    
    // 显示错误提示
    this._showErrorToast(errorMessage);
    
    // 特殊错误处理
    this._handleSpecialErrors(error, errorType);
    
    return true;
  },
  
  /**
   * 处理表单验证错误
   * @param {Error|Object} error 错误对象
   * @param {Object} form 表单对象
   * @returns {Boolean} 是否已处理
   */
  handleFormError: function(error, form = null) {
    console.error('[Form Error]', error);
    
    if (form && error.field) {
      // 设置表单字段错误
      if (typeof form.setError === 'function') {
        form.setError(error.field, error.message);
      }
    } else {
      // 显示一般错误
      this._showErrorToast(this._getErrorMessage(error));
    }
    
    return true;
  },
  
  /**
   * 创建异常
   * @param {String} message 错误消息
   * @param {String} type 错误类型
   * @param {Object} data 附加数据
   * @returns {Object} 标准化的错误对象
   */
  createError: function(message, type = ERROR_TYPES.BUSINESS, data = {}) {
    const error = new Error(message);
    error.type = type;
    error.data = data;
    error.timestamp = dayjs().valueOf();
    return error;
  },
  
  /**
   * 记录错误日志
   * @param {Error|Object} error 错误对象
   * @param {String} context 错误上下文
   */
  logError: function(error, context = '') {
    console.error(`[Error Log] ${context}:`, error);
    
    // 添加到errorStore
    errorStore.addError(error, context);
    
    // 可以在这里实现更复杂的日志记录
    // 例如发送到服务器、存储到本地等
    if (error && (error.type === ERROR_TYPES.SYSTEM || error.type === ERROR_TYPES.UNKNOWN)) {
      this._logErrorToServer(error, context);
    }
  },
  
  /**
   * 清除模块错误
   * @param {String} moduleName 模块名称，不传则清除全局错误
   */
  clearError: function(moduleName = null) {
    uiStore.clearError(moduleName);
  },
  
  /**
   * 清除所有错误
   */
  clearAllErrors: function() {
    uiStore.clearAllErrors();
  },
  
  /**
   * 异步操作错误包装器
   * @param {Function} asyncFn 异步函数
   * @param {String} moduleName 模块名称
   * @param {Object} options 错误处理选项
   * @returns {Promise} 包装后的Promise
   */
  wrapAsync: function(asyncFn, moduleName = null, options = {}) {
    return async (...args) => {
      try {
        return await asyncFn(...args);
      } catch (error) {
        this.handlePageError(error, moduleName, options);
        throw error; // 仍然抛出以便上层处理
      }
    };
  },
  
  /**
   * 检查错误限制
   * @private
   */
  _checkErrorLimit: function() {
    const now = dayjs().valueOf();
    const counterData = this._errorCounter;
    
    // 每分钟重置计数
    if (now - counterData.lastResetTime > 60000) {
      counterData.count = 0;
      counterData.lastResetTime = now;
    }
    
    // 增加计数
    counterData.count++;
    
    // 检查是否超出限制
    return counterData.count <= counterData.maxErrorsPerMinute;
  },
  
  /**
   * 创建标准错误对象
   * @private
   */
  _createStandardError: function(originalError, message, type) {
    return {
      message: message,
      type: type,
      timestamp: dayjs().valueOf(),
      details: typeof originalError === 'object' ? originalError : { message: originalError },
      stack: originalError && originalError.stack
    };
  },
  
  /**
   * 获取错误消息
   * @private
   */
  _getErrorMessage: function(error) {
    if (!error) return '未知错误';
    
    // 处理不同类型的错误对象
    if (typeof error === 'string') return error;
    if (error.message) return error.message;
    if (error.errMsg) return error.errMsg;
    if (error.msg) return error.msg;
    
    return '操作失败';
  },
  
  /**
   * 获取错误类型
   * @private
   */
  _getErrorType: function(error) {
    if (!error) return ERROR_TYPES.UNKNOWN;
    
    // 预定义错误
    if (error.type && Object.values(ERROR_TYPES).includes(error.type)) {
      return error.type;
    }
    
    // 网络错误
    if (error.errCode === -1 || error.errMsg && error.errMsg.includes('fail')) {
      return ERROR_TYPES.NETWORK;
    }
    
    // 授权错误
    if (error.errCode === 403 || error.code === 'auth/unauthorized') {
      return ERROR_TYPES.AUTH;
    }
    
    // 验证错误
    if (error.field || error.code === 'validation_failed') {
      return ERROR_TYPES.VALIDATION;
    }
    
    return ERROR_TYPES.UNKNOWN;
  },
  
  /**
   * 显示错误Toast
   * @private
   */
  _showErrorToast: function(message, duration = 2000) {
    uiStore.showError(message, duration);
  },
  
  /**
   * 显示错误对话框
   * @private
   */
  _showErrorModal: function(title, error) {
    const content = typeof error === 'string' ? error : (error.stack || this._getErrorMessage(error));
    
    wx.showModal({
      title: title || '操作失败',
      content: content,
      showCancel: false
    });
  },
  
  /**
   * 记录错误到服务器
   * @private
   */
  _logErrorToServer: function(error, context = '') {
    // 实现错误上报逻辑
    // 这里可以调用云函数或其他API将错误信息发送到服务器
    console.log('错误已记录到服务器:', { error, context });
    
    // 示例：上报到云函数
    // wx.cloud.callFunction({
    //   name: 'logError',
    //   data: {
    //     error: {
    //       message: error.message,
    //       type: error.type,
    //       stack: error.stack,
    //       context: context,
    //       timestamp: dayjs().valueOf()
    //     }
    //   }
    // }).catch(err => {
    //   console.error('上报错误失败:', err);
    // });
  },
  
  /**
   * 处理特殊错误
   * @private
   */
  _handleSpecialErrors: function(error, errorType) {
    // 根据不同错误类型处理
    switch (errorType) {
      case ERROR_TYPES.AUTH:
        // 处理授权错误，例如跳转到登录页面
        // 使用MobX存储的登录状态
        if (userStore.isLoggedIn) {
          userStore.setLoginState(false);
          wx.reLaunch({
            url: '/pages/login/login'
          });
        }
        break;
        
      case ERROR_TYPES.NETWORK:
        // 处理网络错误，例如检查网络状态
        wx.getNetworkType({
          success: function(res) {
            if (res.networkType === 'none') {
              uiStore.showError('网络连接已断开，请检查网络设置', 3000);
            }
          }
        });
        break;
        
      case ERROR_TYPES.PERMISSION:
        // 处理权限错误，例如显示权限设置引导
        wx.showModal({
          title: '权限不足',
          content: '您没有执行此操作的权限，是否联系管理员?',
          confirmText: '联系管理员',
          cancelText: '取消',
          success(res) {
            if (res.confirm) {
              // TODO: 实现管理员联系逻辑
            }
          }
        });
        break;
        
      default:
        // 默认不做特殊处理
        break;
    }
  },
  
  /**
   * 处理特定类型的错误
   */
  handleErrorByType(error, errorType = ERROR_TYPES.UNKNOWN) {
    // ... existing code ...
    
    // 根据不同错误类型处理
    switch (errorType) {
      case ERROR_TYPES.AUTH:
        // 处理授权错误，例如跳转到登录页面
        // 使用MobX存储的登录状态
        if (userStore.isLoggedIn) {
          userStore.setLoginState(false);
          wx.reLaunch({
            url: '/pages/login/login'
          });
        }
        break;
        
      // ... existing code ...
    }
  }
};

// 创建错误处理Store
export const errorStore = observable({
  // 错误列表
  errors: [],
  
  // 最大错误数量
  maxErrors: 50,
  
  // 添加错误
  addError: action(function(error, context = '') {
    // 创建错误记录
    const errorRecord = {
      message: errorHandler._getErrorMessage(error),
      type: errorHandler._getErrorType(error),
      timestamp: dayjs().valueOf(),
      context: context,
      details: typeof error === 'object' ? error : { message: error },
      stack: error && error.stack
    };
    
    // 添加到错误列表
    this.errors.unshift(errorRecord);
    
    // 限制数量
    if (this.errors.length > this.maxErrors) {
      this.errors = this.errors.slice(0, this.maxErrors);
    }
  }),
  
  // 清除所有错误
  clearErrors: action(function() {
    this.errors = [];
  }),
  
  // 获取特定类型的错误
  getErrorsByType: function(type) {
    return this.errors.filter(err => err.type === type);
  },
  
  // 获取最新的错误
  getLatestError: function() {
    return this.errors.length > 0 ? this.errors[0] : null;
  }
});

// 应用标准化Store
export default standardizeGlobalStore(errorStore, 'error_handler'); 